package com.example.security6atguigu.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
// @EnableWebSecurity注解用于开启Spring Security的自定义配置功能[在springboot项目种可以省略此注解]
@EnableWebSecurity
// 开启基于方法的授权
@EnableMethodSecurity
public class WebSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        http
                // 开启HTTP基本认证
                .authorizeRequests(
                        authorize -> authorize
//                                .requestMatchers("/user/list").hasAuthority("USER_LIST")
//                                .requestMatchers("/user/add").hasAuthority("USER_ADD")
//                                .requestMatchers("/user/**").hasRole("admin")
                                // 所有请求都需要认证
                                .anyRequest()
                                // 已认证的请求会被自动授权
                                .authenticated()
                )
                // 表单登录配置
                .formLogin(
                        form ->
                                form.loginPage("/login")
                                        .permitAll() // 允许所有用户访问登录页面
                                        .usernameParameter("myUsername") // 配置自定义的表单用户名参数，默认值是username
                                        .passwordParameter("myPassword") // 配置自定义的表单密码参数，默认值是password
                                        .successHandler(new MyAuthenticationSuccessHandler()) // 认证成功时的处理
                                        .failureHandler(new MyAuthenticationFailureHandler()) // 认证失败时的处理
                ) // 使用表单授权方式
                // logout : 注销配置
                .logout(logout -> logout.logoutSuccessHandler(
                        new MyLogoutSuccessHandler() // 注销成功时的处理
                ))
                // authenticationEntryPoint : 身份验证入口点
                // exceptionHandling : 异常处理
                .exceptionHandling(exception -> {
                    // 认证失败时的处理[请求未认证的处理]
                    exception.authenticationEntryPoint(new MyAuthenticationEntryPoint());
                    // 访问被拒绝时的处理[无权限访问时的处理]
                    exception.accessDeniedHandler(new MyAccessDeniedHandler());
                })
                // sessionManagement : 会话管理配置
                .sessionManagement(session -> session
                        // 同一用户同时登录的最大数量
                        .maximumSessions(1)
                        // 同一用户的session失效策略
                        .expiredSessionStrategy(new MySessionInformationExpiredStrategy())
                );
                //.httpBasic(withDefaults()); // 使用基本授权方式

        http.csrf(AbstractHttpConfigurer::disable); // 禁用CSRF防护
        return http.build();
    }

//    @Bean
//    public UserDetailsService userDetailsService(){
//        // 创建基于内存的用户信息管理器
//        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
//        // 使用manager管理UserDetailsService对象
//        manager.createUser(
//                // 创建UserDetailsService对象，用于管理用户名，用户密码，用户角色，用户权限等信息
//                User.withDefaultPasswordEncoder().username("lll").password("111").roles("USER").build()
//        );
//        return manager;
//    }

//    @Bean
//    public UserDetailsService userDetailsService(){
//        // 创建基于数据库的用户信息管理器
//        return new DBUserDetailsManager();
//    }

}
